namespace Crux.Core.Websockets.Redis;
/// <summary>
///
/// </summary>
internal class RedisSubscriptionManager
{
    /// <summary>
    ///
    /// </summary>
    private readonly ConcurrentDictionary<string, WebSocketConnectionStore> _subscriptions = new ConcurrentDictionary<string, WebSocketConnectionStore>();
    /// <summary>
    ///
    /// </summary>
    private readonly SemaphoreSlim _lock = new SemaphoreSlim(1, 1);
    /// <summary>
    ///
    /// </summary>
    public async Task AddSubscriptionAsync(
        string id,
        WebSocketConnectionContext context,
        Func<string, WebSocketConnectionStore, Task> subscribeMethod)
    {
        await _lock.WaitAsync(context.ConnectionAborted).ConfigureAwait(false);

        try
        {
            var subscription = _subscriptions.GetOrAdd(id, _ => new WebSocketConnectionStore());
            subscription.Add(context);

            if (subscribeMethod is not null)
            {
                await subscribeMethod(id, subscription).ConfigureAwait(false);
            }
        }
        finally
        {
            _lock.Release();
        }
    }
    /// <summary>
    ///
    /// </summary>
    public async Task RemoveSubscriptionAsync(
        string id,
        WebSocketConnectionContext context,
        Func<string, Task> unsubscribeMethod)
    {
        await _lock.WaitAsync(context.ConnectionAborted).ConfigureAwait(false);

        try
        {
            if (!_subscriptions.TryGetValue(id, out var subscription))
            {
                return;
            }

            subscription.Remove(context);

            if (0 == subscription.Count)
            {
                _subscriptions.TryRemove(id, out _);

                await unsubscribeMethod(id).ConfigureAwait(false);
            }
        }
        finally
        {
            _lock.Release();
        }
    }
}
